﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Net;
using System.Net.Mail;
using System.Data;
using System.Xml.Serialization;
using System.Configuration;

namespace SpeedTestReports.Web
{
    /// <summary>
    /// Summary description for XAMLReports
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class XAMLReports : System.Web.Services.WebService
    {
        
        [XmlInclude(typeof(SelectionValue))]
        [WebMethod]
        public string GetReport(string userName, string password, string reportID, SelectionValue[] selections)
        {
            XAMLGen xamlgen = new XAMLGen();
            Data data = new Data();
            string errMsg = String.Empty;

            if (ConnectAndAuthenticate(data, userName, password, out errMsg))
            {
                string report = xamlgen.GenerateReport(data, reportID, selections);
                data.Disconnect();
                return report;
            }

            data.Disconnect();
            return xamlgen.GenerateError(errMsg);
        }

        [WebMethod]
        public string GetSelector(string userName, string password, string reportID)
        {
            XAMLGen xamlgen = new XAMLGen();
            Data data = new Data();
            string errMsg = String.Empty;

            if (ConnectAndAuthenticate(data, userName, password, out errMsg))
            {
                DataTable selTable = data.GetSelectionsByReportID(reportID);

                if (selTable != null)
                {

                    string selectionPanel = xamlgen.GenerateSelectionPanel(selTable, data, reportID, "1", null);   //the default sequence
                    data.Disconnect();
                    return selectionPanel;
                }
            }

            data.Disconnect();
            return xamlgen.GenerateError(errMsg);
        }

        [WebMethod]
        public string GetNextSelector(string userName, string password, string sequence, string reportID, SelectionValue[] selections)
        {
            XAMLGen xamlgen = new XAMLGen();
            Data data = new Data();
            string errMsg = String.Empty;

            if(ConnectAndAuthenticate(data, userName, password, out errMsg))
            {
                DataTable selTable = data.GetSelectionsByReportID(reportID);

                if (selTable != null)
                {
                    string selectionPanel = xamlgen.GenerateSelectionPanel(selTable, data, reportID, sequence, selections);   //the default sequence
                    data.Disconnect();
                    return selectionPanel;
                }
            }

            data.Disconnect();
            return xamlgen.GenerateError(errMsg);
        }

        [WebMethod]
        public string GetReportList(string userName, string password)
        {
            XAMLGen xGen = new XAMLGen();
            Data data = new Data();
            string errMsg = String.Empty;

            if(ConnectAndAuthenticate(data, userName, password, out errMsg))
            {
                DataTable table = data.GetReportList();

                string reportTree = xGen.GenerateReportTree(table);
                data.Disconnect();
                return reportTree;
            }
            else {return xGen.GenerateError(errMsg);}
        }

        [WebMethod]
        public bool AuthenticateUser(string userName, string password)
        {
            Data data = new Data();
            string errMsg = String.Empty;

            if (ConnectAndAuthenticate(data, userName, password, out errMsg))
            {
                data.Disconnect();
                return true;
            }
            else { return false; }
        }

        [WebMethod]
        public string RegisterUser(string name, string email, string userName, string password, string confirmedPwd)
        {
            Data data = new Data();
            string errMsg = String.Empty;

            if (ConnectData(data, out errMsg))
            {
                if (data.CheckUserNameAvailability(userName))
                {
                    if (data.InsertUser(name, email, userName, password))
                    {
                        data.Disconnect();
                        return "SUCCESS";
                    }
                    else
                    {
                        data.Disconnect();
                        return "ERROR: Unable to create user. Please contact the site administrator.";
                    }
                }
                else
                {
                    data.Disconnect();
                    return "ERROR: User Name already exists";
                }
            }
            else { return "ERROR:" + errMsg; }
            //if it fails, "ERROR" + return error message - like User Name in use.
            data.Disconnect();
            return "SUCCESS";
        }

        [WebMethod]
        public bool ResendPassword(string userName)
        {
            Data data = new Data();
            string errMsg = String.Empty;
            if (ConnectData(data, out errMsg))
            {
                DataTable table = data.GetUserByUserName(userName);

                if (table != null && table.Rows.Count > 0)
                {
                    if (SendMail(table.Rows[0]["email"].ToString(), table.Rows[0]["userName"].ToString(),
                        table.Rows[0]["password"].ToString()))
                    {
                        data.Disconnect();
                        return true;
                    }
                }
            }

            return false;
        }

        private bool SendMail(string email, string userName, string password)
        {
            if (String.IsNullOrEmpty(email) || String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(password)) { return false; }

            string address = ConfigurationManager.AppSettings.Get("SMTPDisplayAddress");
            string displayName = ConfigurationManager.AppSettings.Get("SMTPDisplayName");
            string host = ConfigurationManager.AppSettings.Get("SMTPHost");
            int port = 0;
            Int32.TryParse(ConfigurationManager.AppSettings.Get("SMTPPort"), out port);
            string smtpUserName = ConfigurationManager.AppSettings.Get("SMTPUserName");
            string smtpPassword = ConfigurationManager.AppSettings.Get("SMTPPassword");
            bool useSSL;
            Boolean.TryParse(ConfigurationManager.AppSettings.Get("SMTPUseSSL"), out useSSL);

            //if any are empty, return false
            if (String.IsNullOrEmpty(address) || String.IsNullOrEmpty(displayName) || String.IsNullOrEmpty(host) || 
                String.IsNullOrEmpty(smtpUserName) || String.IsNullOrEmpty(smtpPassword)) { return false; }
            
            try
            {
                MailAddress from = new MailAddress(address, displayName);
                MailAddress to = new MailAddress(email);
                MailMessage message = new MailMessage(from, to);
                message.Subject = "Password Recovery From Speed Test";
                message.Body = "A password recovery message has been requested. If you did not request this message, please contact the administrator of the system." + System.Environment.NewLine;
                message.Body += "User Name: " + userName + System.Environment.NewLine;
                message.Body += "Password: " + password + System.Environment.NewLine;

                SmtpClient client = new SmtpClient();
                client.Host = host;
                client.UseDefaultCredentials = false;
                client.Port = port;
                client.Credentials = new NetworkCredential(smtpUserName, smtpPassword);
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.EnableSsl = useSSL;

           
                client.Send(message);
                return true;
            }
            catch (Exception ex)
            {
                string s = ex.Message;      //TODO: Log this.
                return false;
            }
        }

        [WebMethod]
        public string GetDashboardReport(string userName, string password)
        {
            XAMLGen xamlgen = new XAMLGen();
            Data data = new Data();
            string errMsg = String.Empty;

            if (ConnectAndAuthenticate(data, userName, password, out errMsg))
            {
                string dashboardReport = xamlgen.GenerateDashboard(data);
                data.Disconnect();
                return dashboardReport;
            }
            else
            {
                return xamlgen.GenerateError(errMsg);
            }
        }

        private bool ConnectAndAuthenticate(Data data, string userName, string password, out string errMsg)
        {
            errMsg = String.Empty;

            if(ConnectData(data, out errMsg))
            {
                if (data.Authenticate(userName, password))
                {
                    return true;
                }
                else 
                {
                    data.Disconnect();
                    errMsg = "Authentication failed. Invalid user name or password"; 
                }
            }
            else
            {
                return false;
            }
      
            return false;
        }

        private bool ConnectData(Data data, out string errMsg)
        {
            errMsg = String.Empty;

            //string dbURL = "127.0.0.1"; //default
            //data.ConnectionString = "Server=" + dbURL + ";Port=5432;User Id=speedtestadmin;Password=speedtestadmin;Database=speedtest;";
            data.ConnectionString = ConfigurationManager.AppSettings.Get("PGSConnString");
            data.Connect();

            if (data.State == ConnectionState.Connected)
            {
                return true;
            }
            else
            {
                errMsg = "An error occurred while attempting to connect to the database. Please contact your administrator.";
                return false;
            }
        }
    }
}
